//ok
namespace hjc {

    export class Button extends BaseUI implements ITextural, ITextual, ITouchable {

        protected $bg: string;
        protected $bgDown: string;
        protected $bgDisabled: string;
        protected $text: string;
        protected $textDown: string;
        protected $textDisabled: string;
        protected $textSize: number;
        protected $textColor: number;
        protected $textColorDown: number;
        protected $textColorDisabled: number;
        protected $clickMode: hjc.ClickMode;
        protected $sound: string;
        protected bgImg: eui.Image;
        protected lbl: eui.Label;
        protected $released: boolean;
        protected $clicked: Function;
        protected $pressed: Function;
        protected $context: any;

        public get bg(): string { return this.$bg ? this.$bg : ''; }
        public set bg(bg: string) { this.$bg = bg; }
        public get bgDown(): string { return this.$bgDown ? this.$bgDown : this.bg; }
        public set bgDown(bgDown: string) { this.$bgDown = bgDown; }
        public get bgDisabled(): string { return this.$bgDisabled ? this.$bgDisabled : this.bg; }
        public set bgDisabled(bgDisabled: string) { this.$bgDisabled = bgDisabled; }
        public get text(): string { return this.$text; }
        public set text(text: string) { this.$text = text; }
        public get textDown(): string { return this.$textDown ? this.$textDown : this.$text; }
        public set textDown(textDown: string) { this.$textDown = textDown; }
        public get textDisabled(): string { return this.$textDisabled ? this.$textDisabled : this.$text; }
        public set textDisabled(textDisabled: string) { this.$textDisabled = textDisabled; }
        public get textSize(): number { return this.$textSize; }
        public set textSize(size: number) { this.$textSize = size; }
        public get textColor(): number { return this.$textColor; }
        public set textColor(color: number) { this.$textColor = color; }
        public get textColorDown(): number { return this.$textColorDown ? this.$textColorDown : this.$textColor; }
        public set textColorDown(colorDown: number) { this.$textColorDown = colorDown; }
        public get textColorDisabled(): number { return this.$textColorDisabled ? this.$textColorDisabled : this.$textColor; }
        public set textColorDisabled(colorDisabled: number) { this.$textColorDisabled = colorDisabled; }
        public get clickMode(): hjc.ClickMode { return this.$clickMode; }
        public set clickMode(mode: hjc.ClickMode) { this.$clickMode = mode; }
        public get sound(): string { return this.$sound; }
        public set sound(sound: string) { this.$sound = sound; }
        public getLbl(): eui.Label {
            return this.lbl;
        }

        protected _init(): void {
            this.name = "按钮";
            this.$released = true;
            this.$sound = 'click_wav';//todo default
            this.$clickMode = hjc.ClickMode.BOTH_RCV;
            this.$textSize = Font.Size.MID;
            this.$text = "";
            this.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this._onTouchBegin, this);
        }

        protected _created(): void {
            ui.clearPadding(this.content);
            if (this.explicitWidth && this.explicitHeight) ui.fillParent(ui.setCenter(this.content));
            if (!this.$bg) this.setBgS9grids(hjc.Skin.Default.BUTTON_S9GRIDS);
        }

        public setBg(bg: string, s9grids?: hjc.S9GridsOpitons, bgDisabled?: string, bgDown?: string): Button {
            this.$bg = bg;
            if (notEmpty(s9grids)) this.setBgS9grids(s9grids);
            if (bgDisabled) this.$bgDisabled = bgDisabled;
            if (bgDown) this.$bgDown = bgDown;
            this.invalidateState();
            return this;
        }

        public setBgS9grids(s9grids: hjc.S9GridsOpitons): Button {
            ui.setS9grids(this.bgImg, s9grids);
            this.invalidateState();
            return this;
        }

        public setText(text: string, params?: TText): Button {
            this.$text = text;
            this.invalidateState();;
            if (notEmpty(params)) ui.setText(this.lbl, params);
            return this;
        }

        public setTextVertial(vertical: boolean = true): Button {
            this.lbl.multiline = vertical ? false : true;
            this.lbl.maxWidth = vertical ? this.width : null;
            this.invalidateState();
            return this;
        }

        protected getCurrentState(): string {
            let state = super.getCurrentState();
            if (state === hjc.Skin.State.UP && !this.$released) return hjc.Skin.State.DOWN;
            else return state;
        }

        public setClicked(clicked: Function, context?: any): Button {
            this.$clicked = clicked;
            if (context) this.$context = context;
            return this;
        }

        public setPressed(pressed: Function, context?: any): Button {
            this.$pressed = pressed;
            if (context) this.$context = context;
            return this;
        }

        public setSound(sound: string): Button {
            this.$sound = sound;
            return this;
        }

        private _onTouchBegin(): void {
            this.removeEventListener(egret.TouchEvent.TOUCH_BEGIN, this._onTouchBegin, this);
            this.addEventListener(egret.TouchEvent.TOUCH_END, this._onTouchEnd, this);
            this.addEventListener(egret.TouchEvent.TOUCH_RELEASE_OUTSIDE, this._onTouchEnd, this);
            if (this.$sound && RES.getRes(this.$sound)) RES.getRes(this.$sound).play(0, 1);
            this.invalidateState();
            this.$released = false;
            this._playPress(() => {
                if (isFunc(this.$pressed)) this.$context ? Reflect.apply(this.$pressed, this.$context, []) : this.$pressed();
            });
        }

        private _onTouchEnd(evt: egret.TouchEvent): void {
            this.removeEventListener(egret.TouchEvent.TOUCH_END, this._onTouchEnd, this);
            this.removeEventListener(egret.TouchEvent.TOUCH_RELEASE_OUTSIDE, this._onTouchEnd, this);
            this._playRelease(() => {
                this.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this._onTouchBegin, this);
                this._applyClick(evt.type != egret.TouchEvent.TOUCH_RELEASE_OUTSIDE);
            });
        }

        protected _applyClick(inside: boolean): void {
            if (isFunc(this.$clicked)) this.$context ? Reflect.apply(this.$clicked, this.$context, [inside]) : this.$clicked(inside);
        }

        private _playPress(cb: Function): void {
            switch (this.clickMode) {
                case hjc.ClickMode.NONE: cb(); break;
                case hjc.ClickMode.SCALE_RCV: egret.Tween.get(this.content).to({ scaleX: game.clickedScale, scaleY: game.clickedScale }, 150, egret.Ease.sineOut).call(() => cb()); break;
                case hjc.ClickMode.LIGHT_RCV: {
                    effect.toLight(this.content);
                    cb();
                } break;
                case hjc.ClickMode.BOTH_RCV: {
                    effect.toLight(this.content);
                    egret.Tween.get(this.content).to({ scaleX: game.clickedScale, scaleY: game.clickedScale }, 150, egret.Ease.sineOut).call(() => cb());
                } break;
                case hjc.ClickMode.ALPHA_RCV: {
                    this.content.alpha = game.clickedAlpha;
                    cb();
                } break;
                default: console.warn('不存在的按下动画类型：', this.clickMode);
            }
        }

        private _playRelease(cb: Function): void {
            this.$released = true;
            this.invalidateState();
            egret.Tween.removeTweens(this.content);
            switch (this.clickMode) {
                case hjc.ClickMode.NONE: cb(); break;
                case hjc.ClickMode.SCALE_RCV: egret.Tween.get(this.content).to({ scaleX: 1, scaleY: 1, }, 150, egret.Ease.backOut).call(() => cb()); break;
                case hjc.ClickMode.LIGHT_RCV: {
                    effect.removeColor(this.content);
                    cb();
                }; break;
                case hjc.ClickMode.BOTH_RCV: {
                    effect.removeColor(this.content);
                    egret.Tween.get(this.content).to({ scaleX: 1, scaleY: 1, }, 150, egret.Ease.backOut).call(() => cb());
                } break;
                case hjc.ClickMode.ALPHA_RCV: {
                    this.content.alpha = 1;
                    cb();
                } break;
                default: console.warn('不存在的释放动画类型：', this.clickMode);
            }
        }
    }
}